home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / scangen.doc < prev    next >
Text File  |  1992-09-25  |  50KB  |  3,515 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.  
  14.                                    Efficient Generation of
  15.                                    Table-Driven Scanners
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                 Efficient Generation of Table-Driven Scanners
  82.                                       or
  83.                NFA to DFA Conversion in Practically Linear Time
  84.  
  85.  
  86.                                  Josef Grosch
  87.  
  88.  
  89.                                  May 24, 1987
  90.  
  91.          ___________________________________________________________
  92.  
  93.  
  94.                                  Report No. 2
  95.  
  96.  
  97.                              Copyright c 1987 GMD
  98.  
  99.  
  100.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  101.                 Forschungsstelle an der Universitaet Karlsruhe
  102.                           Vincenz-Priesznitz-Str. 1
  103.                                D-7500 Karlsruhe
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.                   Efficient Generation of Lexical Analysers
  140.  
  141.  
  142.  
  143.  
  144.  
  145.                                   J. Grosch
  146.  
  147.  
  148.               GMD Forschungsstelle an der Universitaet Karlsruhe
  149.  
  150.  
  151.              Vincenz-Priesznitz-Str. 1, D-7500 Karlsruhe, Germany
  152.  
  153.  
  154.                            grosch@karlsruhe.gmd.de
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.                                                                              1
  202.  
  203.  
  204.                                    SUMMARY
  205.  
  206.  
  207.  
  208. General tools for the automatic  generation  of  lexical  analysers  like  LEX
  209.  
  210.  
  211. [Les75]  convert  a  specification  consisting of a set of regular expressions
  212.  
  213.  
  214. into a deterministic finite automaton. The main algorithms involved are subset
  215.  
  216.  
  217. construction,  state minimization, and table compression.  Even if these algo-
  218.  
  219.  
  220. rithms do not show their worst case time behaviour they are still quite expen-
  221.  
  222.  
  223. sive.  This  paper shows how to solve the problem in linear time for practical
  224.  
  225.  
  226. cases, thus resulting in a significant speed-up. The idea is  to  combine  the
  227.  
  228.  
  229. automaton  introduced  by Aho and Corasick [AhC75] with the direct computation
  230.  
  231.  
  232. of an efficient table representation. Besides the algorithm we present experi-
  233.  
  234.  
  235. mental  results  of  the  scanner generator Rex [Gro87a] which uses this tech-
  236.  
  237.  
  238. nique.
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245. KEY WORDS  lexical analysis  scanner generator
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.                                                                              2
  267.  
  268.  
  269.                                  INTRODUCTION
  270.  
  271.  
  272.  
  273.      Today, there exist several tools to generate lexical analysers like  e.g.
  274.  
  275.  
  276. LEX  [Les75],  flex  [Pax88],  GLA  [Heu86,Wai86],  ALEX  [Moes86],  or Mkscan
  277.  
  278.  
  279. [HoL87]. This indicates that the automatic implementation of scanners  becomes
  280.  
  281.  
  282. accepted by today's compiler writers. In the past, the low performance of gen-
  283.  
  284.  
  285. erated scanners in comparison to hand-written ones  may  have  restricted  the
  286.  
  287.  
  288. generation  approach to prototyping applications. However, since newer results
  289.  
  290.  
  291. [Gro87b,Heu86,Wai86] show that generated scanners have reached  the  speed  of
  292.  
  293.  
  294. hand-written  ones  there is no argument against using automatically generated
  295.  
  296.  
  297. lexical analysers in production compilers.  In the  following  we  present  an
  298.  
  299.  
  300. efficient  algorithm  to  convert  a  scanner  specification  based on regular
  301.  
  302.  
  303. expressions into a deterministic finite automaton.
  304.  
  305.  
  306.  
  307.      A specification of a scanner consists of a  set  of  regular  expressions
  308.  
  309.  
  310. (REs).  Each RE usually describes a deterministic finite automaton (DFA) being
  311.  
  312.  
  313. able to recognize a token. The whole set of REs, however, usually specifies  a
  314.  
  315.  
  316. nondeterministic  finite  automaton  (NFA).  To  allow  scanning to be done in
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.                                                                              3
  332.  
  333.  
  334. linear time the NFA has to be converted into a DFA. This problem can be solved
  335.  
  336.  
  337. with  well  known  algorithms  for  subset construction and state minimization
  338.  
  339.  
  340. [ASU86,WaG84].  In the worst case subset construction  takes  time  O(2n)  and
  341.  
  342.  
  343. state  minimization  O(n2) or O(n log n) if n is the number of states.  If the
  344.  
  345.  
  346. DFA is implemented as a table-driven automaton  an  additional  algorithm  for
  347.  
  348.  
  349. table-compression is needed in practice, usually taking time O(n2).
  350.  
  351.     Running example:
  352.  
  353.  
  354.     letter ( letter | digit ) *   -> IdentSymbol
  355.  
  356.  
  357.     digit +                       -> DecimalSymbol
  358.  
  359.  
  360.     octdigit + Q                  -> OctalSymbol
  361.  
  362.  
  363.     BEGIN                         -> BeginSymbol
  364.  
  365.  
  366.     END                           -> EndSymbol
  367.  
  368.  
  369.     :=                            -> AssignSymbol
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378. Fig. 1: NFA for the running example
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.                                                                              4
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403. Fig. 2: DFA for the running example (A \ B stands for A-Z,a-z,0-9 except B)
  404.  
  405.  
  406.  
  407.      The above specification describes six  tokens  each  by  a  RE  using  an
  408.  
  409.  
  410. abstract  notation.   The  automaton for these tokens is a NFA whose graphical
  411.  
  412.  
  413. representation is shown in Figure 1.  The conversion of  this  NFA  to  a  DFA
  414.  
  415.  
  416. yields the automaton shown in Figure 2.
  417.  
  418.  
  419.  
  420.  
  421. Definition 1: constant RE
  422.  
  423.  
  424.  
  425.      A RE consisting only of the concatenation of characters is called a  con-
  426.  
  427.  
  428. stant RE. A constant RE contains no operators like  +  *  |  ?
  429.  
  430.  
  431.  
  432.      The language of a constant RE contains exactly one  word.  In  the  above
  433.  
  434.  
  435. example the constant REs are:
  436.  
  437.  
  438.  
  439.     BEGIN  END  :=
  440.  
  441.  
  442.  
  443.  
  444.      During the construction of tables for a DFA by hand we observed that  the
  445.  
  446.  
  447. task  was solvable easily and in linear time for constant REs. Common prefixes
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.                                                                              5
  462.  
  463.  
  464. have simply to be factored out thus arriving at a DFA having a  decision  tree
  465.  
  466.  
  467. as  its  graphical representation. Only the few non-constant REs required real
  468.  
  469.  
  470. work.
  471.  
  472.  
  473.  
  474.      Scanner specifications for languages like Modula or C usually contain 90%
  475.  
  476.  
  477. constant  REs: 60% keywords and 30% delimiters.  Only 10% are non-constant REs
  478.  
  479.  
  480. needed to specify identifiers, various constants, and comments (see Appendix 2
  481.  
  482.  
  483. for an example).  The languages Ada and Pascal are exceptions from this obser-
  484.  
  485.  
  486. vation because keywords can be written in upper or lower case  letters  or  in
  487.  
  488.  
  489. any mixture.
  490.  
  491.  
  492.  
  493.      It would be nice to retain the linear time behaviour for constant REs and
  494.  
  495.  
  496. perform  subset  construction  and  state  minimization  only for the few non-
  497.  
  498.  
  499. constant REs.  The following chapter describes how this  can  be  achieved  by
  500.  
  501.  
  502. first  converting  the  NFA of the non-constant REs to a DFA and incrementally
  503.  
  504.  
  505. adding the constant REs afterwards.  The results of this method are shown  for
  506.  
  507.  
  508. the  running  example.  Then we generalize the method to automata with several
  509.  
  510.  
  511. start states. We conclude with a comparison of  some  scanner  generators  and
  512.  
  513.  
  514. present experimental results.
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.                                                                              6
  528.  
  529.  
  530.                                   THE METHOD
  531.  
  532.  
  533.  
  534.      The basic idea is to combine the special automaton of  Aho  and  Corasick
  535.  
  536.  
  537. [AhC75] with the so-called "comb-vector" or row displacement technique [ASU86]
  538.  
  539.  
  540. for the table representation. The automaton of Aho and Corasick, called a pat-
  541.  
  542.  
  543. tern matching machine, extends a usual DFA by a so-called failure function and
  544.  
  545.  
  546. was originally used to search for overlapping occurrences of  several  strings
  547.  
  548.  
  549. in a given text. This automaton can also be used to cope with a certain amount
  550.  
  551.  
  552. of nondeterminism.
  553.  
  554.  
  555.  
  556.      To introduce the terminology needed we present a definition of  our  ver-
  557.  
  558.  
  559. sion  of  the automaton. We call it a tunnel automaton and the tunnel function
  560.  
  561.  
  562. used corresponds to the failure function of Aho and Corasick.  The name tunnel
  563.  
  564.  
  565. automaton  is  motivated by the analogy to the tunnel effect from nuclear phy-
  566.  
  567.  
  568. sics: Electrons can switch over to another orbit without supply of energy  and
  569.  
  570.  
  571. the tunnel automaton can change its state without consumption of an input sym-
  572.  
  573.  
  574. bol.
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.                                                                              7
  592.  
  593.  
  594. Definition 2: tunnel automaton
  595.  
  596.  
  597.  
  598.      A tunnel automaton is an extension of a DFA and consists of:
  599.  
  600.  
  601.  
  602. StateSet      a finite set of states
  603.  
  604.  
  605. FinalStates   a set of final states                 FinalStates  StateSet
  606.  
  607.  
  608. StartState    a distinguished start state           StartState  StateSet
  609.  
  610.  
  611. Vocabulary    a finite set of input symbols
  612.  
  613.  
  614. Control       the transition function               Control: StateSet x Vocabulary -> StateSet
  615.  
  616.  
  617. NoState       a special state to denote undefined   NoState  StateSet
  618.  
  619.  
  620. Semantics     a function mapping the states         Semantics: StateSet -> 2Proc
  621.  
  622.  
  623.                 to subsets of a set of procedures
  624.  
  625.  
  626. Tunnel        a function mapping states to states   Tunnel: StateSet -> StateSet
  627.  
  628.  
  629.  
  630.  
  631.      A tunnel automaton usually works like a DFA: in each step it  consumes  a
  632.  
  633.  
  634. symbol  and  performs a state transition. Additionally the tunnel automaton is
  635.  
  636.  
  637. allowed to change from state s to state  t = Tunnel (s)  without  consuming  a
  638.  
  639.  
  640. symbol,  if  no  transition  is possible in state s. In state t the same rules
  641.  
  642.  
  643. apply, so the automaton may change the state several times  without  consuming
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.                                                                              8
  658.  
  659.  
  660. any  symbols.   After recognizing a token a semantic procedure associated with
  661.  
  662.  
  663. the final state is executed.  Algorithm 1 formalizes the behaviour of a tunnel
  664.  
  665.  
  666. automaton.   To  guarantee the termination of the WHILE loop the StateStack is
  667.  
  668.  
  669. initialized with a special final state called DefaultState.
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.                                                                              9
  723. Algorithm 1: tunnel automaton
  724.  
  725.  
  726.    BEGIN
  727.  
  728.  
  729.       Push (StateStack , DefaultState)
  730.  
  731.  
  732.       Push (SymbolStack, Dummy       )
  733.  
  734.  
  735.       State  := StartState
  736.  
  737.  
  738.       Symbol := NextSymbol ()
  739.  
  740.  
  741.       LOOP
  742.  
  743.  
  744.          IF Control (State, Symbol) / NoState THEN
  745.  
  746.  
  747.             State := Control (State, Symbol)
  748.  
  749.  
  750.             Push (StateStack , State )
  751.  
  752.  
  753.             Push (SymbolStack, Symbol)
  754.  
  755.  
  756.             Symbol := NextSymbol ()
  757.  
  758.  
  759.          ELSE
  760.  
  761.  
  762.             State := Tunnel (State)
  763.  
  764.  
  765.             IF State = NoState THEN EXIT END
  766.  
  767.  
  768.          END
  769.  
  770.  
  771.       END
  772.  
  773.  
  774.       WHILE NOT Top (StateStack)  FinalStates DO
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.                                                                             10
  788.  
  789.  
  790.          State := Pop (StateStack )
  791.  
  792.  
  793.          UnRead  (Pop (SymbolStack))
  794.  
  795.  
  796.       END
  797.  
  798.  
  799.       Semantics (Top (StateStack)) ()
  800.  
  801.  
  802.    END
  803.  
  804.  
  805.  
  806.  
  807.  
  808.      Before we present the algorithm to compute the control function  we  need
  809.  
  810.  
  811. some more definitions:
  812.  
  813.  
  814.  
  815.  
  816. Definition 3: trace
  817.  
  818.  
  819.  
  820.      The trace of a string is the sequence of states that a  tunnel  automaton
  821.  
  822.  
  823. passes  through  given the string as input. States at which the automaton does
  824.  
  825.  
  826. not consume a symbol are omitted. This includes the start state. If  necessary
  827.  
  828.  
  829. we pad the trace with the value NoState (denoted by the character -) to adjust
  830.  
  831.  
  832. its length to the length of the string.
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.                                                                             11
  852.  
  853.  
  854.     Examples (computed by using the DFA of Fig. 2 as tunnel automaton):
  855.  
  856.  
  857.  
  858.     The trace of   IF      is   1  1
  859.  
  860.  
  861.     The trace of   ENDIF   is   10  11  12  1  1
  862.  
  863.  
  864.     The trace of   1789    is   3  3  2  2
  865.  
  866.  
  867.     The trace of   777Q    is   3  3  3  4
  868.  
  869.  
  870.     The trace of   ::=     is   13  -  -
  871.  
  872.  
  873.  
  874.  
  875.  
  876. Definition 4: ambiguous state
  877.  
  878.  
  879.  
  880.      We call a state s ambiguous (or ambiguously  reachable)  if  there  exist
  881.  
  882.  
  883. more  than  one string such that for each string the repeated execution of the
  884.  
  885.  
  886. control function (first loop in Algorithm 1) ends up in state s.
  887.  
  888.  
  889.  
  890.      Example: The states 1, 2, 3, and 4 of the DFA of  Fig.  2  are  ambiguous
  891.  
  892.  
  893. states.
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900. Method: Construction of a tunnel automaton from a given set of regular expres-
  901.  
  902.  
  903. sions
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917.                                                                             12
  918.  
  919.  
  920. Step 1: Convert the NFA for non-constant REs to a DFA using  the  usual  algo-
  921.  
  922.  
  923.         rithms for subset construction and state minimization [ASU86,WaG84].
  924.  
  925.  
  926.  
  927. Step 2: Extend the DFA to a tunnel automaton by setting Tunnel (s) to  NoState
  928.  
  929.  
  930.         for every state s.
  931.  
  932.  
  933.  
  934. Step 3: Compute the set of ambiguous states of the tunnel automaton.  For con-
  935.  
  936.  
  937.         venience  Appendix  1  contains  an algorithm to compute the ambiguous
  938.  
  939.  
  940.         states.
  941.  
  942.  
  943.  
  944. Step 4: For every constant RE execute Step 5 which incrementally  extends  the
  945.  
  946.  
  947.         tunnel automaton. Continue with Step 6.
  948.  
  949.  
  950.  
  951. Step 5: Compute the trace of the string specified by the constant RE using the
  952.  
  953.  
  954.         current tunnel automaton. We have to distinguish 4 cases:
  955.  
  956.  
  957.  
  958. Case 1: The trace contains neither NoState nor ambiguous states:
  959.  
  960.  
  961.  
  962.  
  963.  
  964.         As the path for the RE already exists include (add) the  semantics  of
  965.  
  966.  
  967.         RE to the semantics of sn and include sn into the set of final states.
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.                                                                             13
  983.  
  984.  
  985. Case 2: The trace does not contain ambiguous states but it contains NoState:
  986.  
  987.  
  988.  
  989.  
  990.  
  991.          Let  si  be  the  last  state  before  NoState.   Extend   the   path
  992.  
  993.  
  994.         s1,  . . . , si  by  newly created states zi+1, . . . , zn. Extend the
  995.  
  996.  
  997.         control function to pass through the states zi+1, . . . , zn given the
  998.  
  999.  
  1000.         input  ai+1, . . . , an  starting  from state si. Set the semantics of
  1001.  
  1002.  
  1003.         the states zi+1, . . . , zn-1 to the empty set.  Set the semantics  of
  1004.  
  1005.  
  1006.         zn to the semantics of RE and include zn into the set of final states.
  1007.  
  1008.  
  1009.         Set the tunnel function of zi+1, . . . , zn to NoState.
  1010.  
  1011.  
  1012.  
  1013. Case 3: The trace does not contain NoState but it contains ambiguous states:
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.         Let si be the first ambiguous state in the trace.  Create  new  states
  1020.  
  1021.  
  1022.         zi, . . . , zn  and  extend  the  control function to pass through the
  1023.  
  1024.  
  1025.         states zi, . . . , zn given the  input  ai, . . . , an  starting  from
  1026.  
  1027.  
  1028.         state  si-1.  Note, that the transition from si-1 to si on input ai is
  1029.  
  1030.  
  1031.         lost this way. Set the semantics of the states zi, . . . , zn  to  the
  1032.  
  1033.  
  1034.         semantics  of  the  corresponding  states si, . . . , sn.  Include the
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.                                                                             14
  1049.  
  1050.  
  1051.         semantics of RE to the semantics of zn and include zn into the set  of
  1052.  
  1053.  
  1054.         final  states.  Set  the  tunnel  function  of  zi, . . . , zn  to the
  1055.  
  1056.  
  1057.         corresponding states si, . . . , sn.
  1058.  
  1059.  
  1060.  
  1061. Case 4: The trace contains ambiguous states as well as NoState:
  1062.  
  1063.  
  1064.  
  1065.         Let si be the first ambiguous state in the trace.  Let sj be the  last
  1066.  
  1067.  
  1068.         state before NoState.  Create new states zi, . . . , zn and extend the
  1069.  
  1070.  
  1071.         control function to pass through the states zi, . . . , zn  given  the
  1072.  
  1073.  
  1074.         input  ai, . . . , an  starting  from  state si-1. Note again that the
  1075.  
  1076.  
  1077.         transition from si-1 to si on input ai  is  lost  this  way.  Set  the
  1078.  
  1079.  
  1080.         semantics  of  the  states  zi, . . . , zj  to  the  semantics  of the
  1081.  
  1082.  
  1083.         corresponding states si, . . . , sj.  Set the semantics of the  states
  1084.  
  1085.  
  1086.         zj+1, . . . , zn-1  to  the empty set.  Set the semantics of zn to the
  1087.  
  1088.  
  1089.         semantics of RE and include zn into the set of final states.  Set  the
  1090.  
  1091.  
  1092.         tunnel   function   of  zi, . . . , zj  to  the  corresponding  states
  1093.  
  1094.  
  1095.         si, . . . , sj  and  set   the   tunnel   function   of   the   states
  1096.  
  1097.  
  1098.         zj+1, . . . , zn to NoState.
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.                                                                             15
  1114.  
  1115.  
  1116. Step 6: If an unambiguous semantic function is desired convert
  1117.  
  1118.  
  1119.  
  1120.             Semantics (s) = { p1,  . . . , pn }     to     Semantics (s) = { pi }
  1121.  
  1122.  
  1123.  
  1124.  
  1125.         for all states s. We  assume  the  procedures  p1,  . . . , pn  to  be
  1126.  
  1127.  
  1128.         ordered  totally  with  pi  being the maximal (see below) procedure of
  1129.  
  1130.  
  1131.         p1,  . . . , pn.
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.      Algorithm 2 describes step 5 more precisely.  The problem of an ambiguous
  1142.  
  1143.  
  1144. semantic  function  arises  already in the running example, as e.g. the string
  1145.  
  1146.  
  1147. END matches both the REs for IdentSymbol and EndSymbol.  Therefore state 12 of
  1148.  
  1149.  
  1150. Fig.  2  would  be associated with two semantic procedures. The generators LEX
  1151.  
  1152.  
  1153. and Rex for example turn the semantic function into an unambiguous one by con-
  1154.  
  1155.  
  1156. sidering  the  sequence  of  the  REs in the given specification.  The REs and
  1157.  
  1158.  
  1159. their associated semantic actions  are  mapped  to  priorities  in  descending
  1160.  
  1161.  
  1162. order. In case of conflicts the semantic action with greatest priority is pre-
  1163.  
  1164.  
  1165. ferred. In other words the procedures are ordered  totally  and  the  "maximal
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.                                                                             16
  1180.  
  1181. Algorithm 2: extend a tunnel automaton to recognize an additional constant RE
  1182.  
  1183.  
  1184. BEGIN
  1185.  
  1186.  
  1187.    State  := StartState
  1188.  
  1189.  
  1190.    Symbol := NextSymbol ()   /* reading the string specified by the constant RE */
  1191.  
  1192.  
  1193.  
  1194.    /* trace and do nothing */
  1195.  
  1196.  
  1197.  
  1198.    LOOP
  1199.  
  1200.  
  1201.       IF Control (State, Symbol) = NoState OR
  1202.  
  1203.  
  1204.          Symbol = EndOfInput OR
  1205.  
  1206.  
  1207.          Control (State, Symbol)  AmbiguousStates THEN EXIT END
  1208.  
  1209.  
  1210.       State  := Control (State, Symbol)   /* trace */
  1211.  
  1212.  
  1213.       Symbol := NextSymbol ()
  1214.  
  1215.  
  1216.    END
  1217.  
  1218.  
  1219.    PreviousState := State
  1220.  
  1221.  
  1222.  
  1223.    /* trace and duplicate the path */
  1224.  
  1225.  
  1226.  
  1227.    LOOP
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.                                                                             17
  1243.  
  1244.  
  1245.       IF Control (State, Symbol) / NoState THEN
  1246.  
  1247.  
  1248.          IF Symbol = EndOfInput THEN EXIT END
  1249.  
  1250.  
  1251.          NewState := CreateState ()
  1252.  
  1253.  
  1254.          State := Control (State, Symbol)   /* trace */
  1255.  
  1256.  
  1257.          Control (PreviousState, Symbol) := NewState
  1258.  
  1259.  
  1260.          Semantics (NewState) := Semantics (State)
  1261.  
  1262.  
  1263.          Tunnel (NewState) := State
  1264.  
  1265.  
  1266.          PreviousState := NewState
  1267.  
  1268.  
  1269.          Symbol := NextSymbol ()
  1270.  
  1271.  
  1272.       ELSE
  1273.  
  1274.  
  1275.          IF Tunnel (State) = NoState THEN EXIT END
  1276.  
  1277.  
  1278.          State := Tunnel (State)
  1279.  
  1280.  
  1281.       END
  1282.  
  1283.  
  1284.    END
  1285.  
  1286.  
  1287.  
  1288.    /* extend the path */
  1289.  
  1290.  
  1291.  
  1292.    WHILE Symbol / EndOfInput DO
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.                                                                             18
  1308.  
  1309.  
  1310.       NewState := CreateState ()
  1311.  
  1312.  
  1313.       Control (PreviousState, Symbol) := NewState
  1314.  
  1315.  
  1316.       Semantics (NewState) :=
  1317.  
  1318.  
  1319.       Tunnel (NewState) := NoState
  1320.  
  1321.  
  1322.       PreviousState := NewState
  1323.  
  1324.  
  1325.       Symbol := NextSymbol ()
  1326.  
  1327.  
  1328.    END
  1329.  
  1330.  
  1331.  
  1332.    /* process new final state */
  1333.  
  1334.  
  1335.  
  1336.    FinalStates := FinalStates U { PreviousState }
  1337.  
  1338.  
  1339.    Semantics (PreviousState) := Semantics (PreviousState) U Semantics (RE)
  1340.  
  1341.  
  1342. END
  1343.  
  1344.  
  1345.  
  1346. procedure" out of several ones is selected.
  1347.  
  1348.  
  1349.  
  1350.      A tunnel automaton extended using Algorithm 2 works correctly because  of
  1351.  
  1352.  
  1353. the  following  reasons.  The constant REs are recognized correctly because of
  1354.  
  1355.  
  1356. the construction used.  We construct a decision  tree  without  any  ambiguous
  1357.  
  1358.  
  1359. states.
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.                                                                             19
  1373.  
  1374.  
  1375.      The non-constant REs are recognized  correctly  because:  If  the  tunnel
  1376.  
  1377.  
  1378. automaton  stops  at a newly created state we have propagated the semantics of
  1379.  
  1380.  
  1381. the original final state to the new one. Otherwise the tunnel  automaton  uses
  1382.  
  1383.  
  1384. at  most one tunnel transition and stops at exactly the same state as it would
  1385.  
  1386.  
  1387. have stopped at before. That is because of  the  construction  of  the  tunnel
  1388.  
  1389.  
  1390. function.  As  we  did not change the semantic function of previously existing
  1391.  
  1392.  
  1393. states, except in the case where we could use the state as final  state  of  a
  1394.  
  1395.  
  1396. constant RE, the automaton behaves as before.
  1397.  
  1398.  
  1399.  
  1400.      We call a tunnel automaton minimal if it has the minimal number of states
  1401.  
  1402.  
  1403. to  do  its job, e. g. it must be able to distinguish between different tokens
  1404.  
  1405.  
  1406. using separate final states.  Without a formal proof we state that Algorithm 2
  1407.  
  1408.  
  1409. constructs  a  minimal  automaton if the given DFA was minimal.  The reason is
  1410.  
  1411.  
  1412. that a tunnel automaton has the same number of states and the same "structure"
  1413.  
  1414.  
  1415. as  a corresponding DFA except that many regular transitions are replaced by a
  1416.  
  1417.  
  1418. few tunnel transitions.  Compare for example the Figures 2 and 3.
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.                                                                             20
  1438.  
  1439.  
  1440.                                    EXAMPLE
  1441.  
  1442.  
  1443.  
  1444.      Algorithm 2 constructs for the running example the tunnel automaton  dep-
  1445.  
  1446.  
  1447. icted  in  Fig. 3. The dotted arrows denote tunnel transitions.  The automaton
  1448.  
  1449.  
  1450. in Fig. 3 is graphically similar to the one in Fig. 2: most of the transitions
  1451.  
  1452.  
  1453. leading  to  state  1 have been replaced by tunnel transitions.  However, note
  1454.  
  1455.  
  1456. the difference: whereas a solid arrow of Fig. 2 stands for a big set of  tran-
  1457.  
  1458.  
  1459. sitions  a  dotted  arrow  of Fig. 3 denotes a single tunnel transition, only.
  1460.  
  1461.  
  1462. This is the key to the efficient representation  of  the  control  and  tunnel
  1463.  
  1464.  
  1465. functions.  As  the  control  function  corresponds  to a sparse matrix it can
  1466.  
  1467.  
  1468. advantageously be implemented using the  comb-vector  technique  [ASU86].  The
  1469.  
  1470.  
  1471. rows  of  a matrix are merged into a single vector called Next. Two additional
  1472.  
  1473.  
  1474. vectors called Base and Check are necessary to accomplish the  access  of  the
  1475.  
  1476.  
  1477. original  data.  The resulting data structure resembles the merging of several
  1478.  
  1479.  
  1480. combs into one. In combination with the above a fourth array called Tunnel  is
  1481.  
  1482.  
  1483. used  to  compress the table even more. This array corresponds directly to our
  1484.  
  1485.  
  1486. tunnel function.  Fig. 4 shows some entries of the comb-vector for the running
  1487.  
  1488.  
  1489. example. The excerpt is restricted to the characters E, N, D.
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.                                                                             21
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511. Fig. 3: tunnel automaton for the running example
  1512.  
  1513.  
  1514.  
  1515.  
  1516.      An advantage of Algorithm 2 is that this data structure  is  computed  in
  1517.  
  1518.  
  1519. part  directly  from  the  set  of REs. There is no need to compute a complete
  1520.  
  1521.  
  1522. classical DFA first and to transform it into the above  data  structure  using
  1523.  
  1524.  
  1525. time  and  space  consuming table compression algorithms afterwards.  The con-
  1526.  
  1527.  
  1528. struction of the comb-vector consists primarily of the computation of the Base
  1529.  
  1530.  
  1531. and the Tunnel values. For each state the Base value is determined by a simple
  1532.  
  1533.  
  1534. search algorithm which shows reasonable results  and  performance.   A  clever
  1535.  
  1536.  
  1537. computation  of  the  Tunnel values is essential for a good table compression.
  1538.  
  1539.  
  1540. Its complexity is O(n2c) where n is the number of states of the DFA and  c  is
  1541.  
  1542.  
  1543. the  cardinality of the character set. For each state an other state has to be
  1544.  
  1545.  
  1546. determined which can safely act as "Tunnel state" and which  saves  a  maximal
  1547.  
  1548.  
  1549. number  of  transitions.  It is sufficient to perform this expensive algorithm
  1550.  
  1551.  
  1552. for the few states created for non-constant REs only. The  Tunnel  values  for
  1553.  
  1554.  
  1555. the  states  created  for constant REs are determined by Algorithm 2 in linear
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.                                                                             22
  1569.  
  1570.  
  1571.  
  1572.  
  1573.          0   1   2   ...   68   69   70   71   72   ...   78   79   80
  1574.  
  1575.  ___________________________________________________________________________
  1576.  
  1577.  
  1578.  Check   -   -   -   ...    0    0    1    1   11   ...    0   10    1   ...
  1579.  
  1580.  ___________________________________________________________________________
  1581.  
  1582.  
  1583.  Next    -   -   -   ...    1   10    1    1   12   ...    1   11    1   ...
  1584.  
  1585.  ___________________________________________________________________________
  1586.  
  1587.  
  1588.       
  1589.  
  1590.  
  1591.  
  1592.  
  1593.  
  1594.  
  1595.  
  1596.           
  1597.  
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603.  
  1604.               
  1605.  
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.                   
  1613.  
  1614.  
  1615.  
  1616.  
  1617.  
  1618.  
  1619.  
  1620.                         
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.                              
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.  
  1636.                                   
  1637.  
  1638.  
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.                                        
  1645.  
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.                                             
  1653.  
  1654.  
  1655.  
  1656.  
  1657.  
  1658.  
  1659.  
  1660.                                                  
  1661.  
  1662.  
  1663.  
  1664.  
  1665.  
  1666.  
  1667.  
  1668.                                                        
  1669.  
  1670.  
  1671.  
  1672.  
  1673.  
  1674.  
  1675.  
  1676.                                                             
  1677.  
  1678.  
  1679.  
  1680.  
  1681.  
  1682.  
  1683.  
  1684.                                                                  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.                                                                       
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.                   State    0   1   ...   10   11   12
  1706.  
  1707.                   _________________________________________
  1708.  
  1709.  
  1710.                   Base     0   2   ...    1    4    0   ...
  1711.  
  1712.                   _________________________________________
  1713.  
  1714.  
  1715.                   Tunnel   -   -   ...    1    1    1   ...
  1716.  
  1717.                   _________________________________________
  1718.  
  1719.  
  1720.                         
  1721.  
  1722.  
  1723.  
  1724.  
  1725.  
  1726.  
  1727.  
  1728.                             
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.                                 
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.                                       
  1745.  
  1746.  
  1747.  
  1748.  
  1749.  
  1750.  
  1751.  
  1752.                                            
  1753.  
  1754.  
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.                                                 
  1761.  
  1762.  
  1763.  
  1764.  
  1765.  
  1766.  
  1767.  
  1768.                                                      
  1769.  
  1770.  
  1771.  
  1772.  
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.           Control (State, Symbol) := IF   Check  [Base  [State]  +  Symbol]  =
  1784.  
  1785.  
  1786. State
  1787.  
  1788.  
  1789.                                      THEN Next  [Base [State] + Symbol]
  1790.  
  1791.  
  1792.                                      ELSE NoState
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.                                                                             23
  1808.  
  1809.  
  1810. Fig. 4: comb vector data structure for the running example and access procedure
  1811.  
  1812.  
  1813.          (for characters E, N, D only; ASCII codes: E=69, D=68, N=78)
  1814.  
  1815.  
  1816.  
  1817. time.
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.                              SEVERAL START STATES
  1825.  
  1826.  
  1827.  
  1828.      Scanner generators like LEX and Rex offer the feature of so-called  start
  1829.  
  1830.  
  1831. states  to handle left context. In each start state a different set of REs may
  1832.  
  1833.  
  1834. be activated and there are special statements  to  change  the  current  start
  1835.  
  1836.  
  1837. state.  A  scanner  specification using several start states is turned into an
  1838.  
  1839.  
  1840. automaton with several start states.  Under these circumstances the  construc-
  1841.  
  1842.  
  1843. tion  algorithm  for a tunnel automaton becomes a little bit more complex.  We
  1844.  
  1845.  
  1846. only mention the problems that arise from this extension.
  1847.  
  1848.  
  1849.  
  1850.      First we have to refine the computation of ambiguous states. Definition 4
  1851.  
  1852.  
  1853. is still valid saying that an ambiguous state must be reachable with more than
  1854.  
  1855.  
  1856. one string. Now we have to take into account that  strings  can  be  processed
  1857.  
  1858.  
  1859. starting  from  several  start states. The difference of the refined algorithm
  1860.  
  1861.  
  1862.  
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.                                                                             24
  1873.  
  1874.  
  1875. lies in the treatment of the states  being  direct  successors  of  the  start
  1876.  
  1877.  
  1878. states. Such a state becomes ambiguous if there exist more than one transition
  1879.  
  1880.  
  1881. from one start state. It is not sufficient if there  are  several  transitions
  1882.  
  1883.  
  1884. but each one originates in a different start state.
  1885.  
  1886.  
  1887.  
  1888.      If a constant RE should be recognized in a set of start states S we would
  1889.  
  1890.  
  1891. like  to  construct  only one sequence of states which can be reached from all
  1892.  
  1893.  
  1894. members of S. This is because we want to create as  few  states  as  possible.
  1895.  
  1896.  
  1897. However,  we  have  to be careful, because the trace of the RE could lead to a
  1898.  
  1899.  
  1900. state which can be reached from a start state t not contained in S. This would
  1901.  
  1902.  
  1903. erroneously  allow  the recognition of the RE also from start state t.  There-
  1904.  
  1905.  
  1906. fore we have to construct several sequences of states or we have to branch off
  1907.  
  1908.  
  1909. an  existing  sequence in this case. To be able to do this we have to know the
  1910.  
  1911.  
  1912. set of start states a state can be reached from.  Step 5 of  the  construction
  1913.  
  1914.  
  1915. of a tunnel automaton has to be extended not only to consider ambiguous states
  1916.  
  1917.  
  1918. but also to check whether the set of start states S of the RE is a proper sub-
  1919.  
  1920.  
  1921. set  of  the set of start states a state in the trace can be reached from.  In
  1922.  
  1923.  
  1924. this case a side branch with newly created states is necessary.
  1925.  
  1926.  
  1927.  
  1928.  
  1929.  
  1930.  
  1931.  
  1932.  
  1933.  
  1934.  
  1935.  
  1936.  
  1937.  
  1938.                                                                             25
  1939.  
  1940.  
  1941.      We extend a tunnel automaton to recognize a RE once for each  correspond-
  1942.  
  1943.  
  1944. ing start state. Our aim is to use the same sequence of states constructed for
  1945.  
  1946.  
  1947. the first start state, but we have to check whether this is  safely  possible.
  1948.  
  1949.  
  1950. To be able to reuse a sequence of states we have to record it. For every char-
  1951.  
  1952.  
  1953. acter (index) and every associated state t from the traces of the RE we record
  1954.  
  1955.  
  1956. the state actually used in the tunnel automaton as target state of the current
  1957.  
  1958.  
  1959. transition. This is either the state t or a newly created one.  The  construc-
  1960.  
  1961.  
  1962. tion  method  is now extended in the following way. For each character index i
  1963.  
  1964.  
  1965. of the RE the state t from the trace is examined. Whenever possible the  state
  1966.  
  1967.  
  1968. recorded for i and t is reused.
  1969.  
  1970.  
  1971.  
  1972.  
  1973.  
  1974.  
  1975.                              EXPERIMENTAL RESULTS
  1976.  
  1977.  
  1978.  
  1979.      The presented method has been used in  a  scanner  generator  called  Rex
  1980.  
  1981.  
  1982. (Regular  EXpression  tool)  which  is  implemented  by  a 5,500 line Modula-2
  1983.  
  1984.  
  1985. [Wir85] program.  It is able to generate  scanners  in  the  languages  C  and
  1986.  
  1987.  
  1988. Modula-2.  The generated scanners are table-driven implementations of a tunnel
  1989.  
  1990.  
  1991.  
  1992.  
  1993.  
  1994.  
  1995.  
  1996.  
  1997.  
  1998.  
  1999.  
  2000.  
  2001.  
  2002.  
  2003.                                                                             26
  2004.  
  2005.  
  2006. automaton. In the following we compare the time to generate a scanner as  well
  2007.  
  2008.  
  2009. as  the speed of the generated scanners for LEX [Les75], flex [Pax88], and Rex
  2010.  
  2011.  
  2012. [Gro87a,Gro88].  Flex is a rewrite of LEX intended to  generate  lexical  ana-
  2013.  
  2014.  
  2015. lysers much faster and the analysers use smaller tables and run faster.
  2016.  
  2017.  
  2018.  
  2019.      To compare the scanner generators  we  used  4  versions  of  a  Modula-2
  2020.  
  2021.  
  2022. scanner  specification  (see  Appendix  2  for an example written in the input
  2023.  
  2024.  
  2025. language of Rex). The versions differ in the number of constant REs  as  shown
  2026.  
  2027.  
  2028. in  Table 1.  Version 1 is incomplete, version 2 omits keywords, version 3 has
  2029.  
  2030.  
  2031. keywords, and version 4 has lower as well as upper case keywords.   The  times
  2032.  
  2033.  
  2034. are  given  in  seconds measured on a MC 68020 processor.  The optimization of
  2035.  
  2036.  
  2037. flex can be controlled by options: usually -cem results in the smallest tables
  2038.  
  2039.  
  2040. and -cf in the fastest analyser.
  2041.  
  2042.  
  2043.  
  2044.      LEX performs well for small specifications but it seems  to  use  a  qua-
  2045.  
  2046.  
  2047. dratic or exponential algorithm for all the REs. This leads to long generation
  2048.  
  2049.  
  2050. times and large tables for large specifications (containing e.  g.  many  key-
  2051.  
  2052.  
  2053. words).
  2054.  
  2055.  
  2056.  
  2057.  
  2058.  
  2059.  
  2060.  
  2061.  
  2062.  
  2063.  
  2064.  
  2065.  
  2066.  
  2067.  
  2068.                                                                             27
  2069.  
  2070.  
  2071.  
  2072.                   Table 1: Comparison of Scanner Generators
  2073.  
  2074.  
  2075.  
  2076. ______________________________________________________________________________
  2077.  
  2078.  
  2079.                                         Spec. 1   Spec. 2   Spec. 3   Spec. 4
  2080.  
  2081. ______________________________________________________________________________
  2082.  
  2083.  
  2084.  # of non-constant REs                       10        10        10        10
  2085.  
  2086.  
  2087.  # of constant REs                            2        29        69       109
  2088.  
  2089.  
  2090.  total # of REs                              12        39        79       119
  2091.  
  2092. ______________________________________________________________________________
  2093.  
  2094.  
  2095.  # of states for non-constant REs            40        40        40        40
  2096.  
  2097.  
  2098.  # of states for constant REs                 0        26       181       336
  2099.  
  2100.  
  2101.  total # of states (generated by Rex)        40        66       221       376
  2102.  
  2103. ______________________________________________________________________________
  2104.  
  2105.  
  2106.  generation time using      LEX            3.14      6.71     73.71    215.08
  2107.  
  2108.  
  2109.  [seconds]                  flex -cem      0.69      0.78      2.01      3.81
  2110.  
  2111.  
  2112.                             flex -cf       1.39      2.35      7.16     12.16
  2113.  
  2114.  
  2115.                             Rex            3.56      3.76      4.91      6.16
  2116.  
  2117. ______________________________________________________________________________
  2118.  
  2119.  
  2120.  table size using           LEX           2,996     4,708    39,156    67,384
  2121.  
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.  
  2130.  
  2131.  
  2132.  
  2133.                                                                             28
  2134.  
  2135.  
  2136.  [bytes]                    flex -cem     1,116     1,376     2,868     4,592
  2137.  
  2138.  
  2139.                             flex -cf     10,744    17,424    57,260    97,096
  2140.  
  2141.  
  2142.                             Rex           3,114     3,218     4,366     5,530
  2143.  
  2144. ______________________________________________________________________________
  2145.  
  2146.  
  2147.  scanner size using         LEX           5,464     8,044    43,756    73,264
  2148.  
  2149.  
  2150.  [bytes]                    flex -cem    14,240    15,368    18,140    21,144
  2151.  
  2152.  
  2153.                             flex -cf     15,452    23,000    64,116   105,232
  2154.  
  2155.  
  2156.                             Rex           8,456     8,884    11,200    13,536
  2157.  
  2158. ______________________________________________________________________________
  2159.  
  2160.  
  2161.  
  2162.  
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  
  2169.  
  2170.  
  2171.  
  2172.  
  2173.  
  2174.  
  2175.  
  2176.  
  2177.  
  2178.  
  2179.  
  2180.  
  2181.  
  2182.  
  2183.  
  2184.  
  2185.  
  2186.  
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.  
  2224.  
  2225.  
  2226.  
  2227.  
  2228.                                      
  2229.  
  2230.  
  2231.  
  2232.  
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.                          
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.  
  2273.  
  2274.  
  2275.  
  2276.  
  2277.  
  2278.  
  2279.  
  2280.  
  2281.  
  2282.  
  2283.  
  2284.  
  2285.  
  2286.  
  2287.  
  2288.  
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295.  
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.  
  2310.  
  2311.  
  2312.  
  2313.  
  2314.  
  2315.  
  2316.  
  2317.  
  2318.  
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.      Flex is quite an improvement compared to LEX especially in terms of  gen-
  2331.  
  2332.  
  2333. eration time. The sizes of the tables and the generated scanners depend on the
  2334.  
  2335.  
  2336. optimization flags: -cem reduces the sizes drastically but  -cf  yields  sizes
  2337.  
  2338.  
  2339. even larger than LEX.
  2340.  
  2341.  
  2342.  
  2343.      The timings of Rex demonstrate its linear behaviour. In general the  gen-
  2344.  
  2345.  
  2346. eration times are not quite as small as those of flex except for specification
  2347.  
  2348.  
  2349. 4.  The expensive algorithms for subset construction, state minimization,  and
  2350.  
  2351.  
  2352. table  compression  are  executed  for 40 states, only. An arbitrary number of
  2353.  
  2354.  
  2355.  
  2356.  
  2357.  
  2358.  
  2359.  
  2360.  
  2361.  
  2362.  
  2363.  
  2364.  
  2365.  
  2366.                                                                             29
  2367.  
  2368.  
  2369. constant REs like keywords can be added  in  a  small,  linear  growing  time.
  2370.  
  2371.  
  2372. Although the generated tables are larger than those of flex the total sizes of
  2373.  
  2374.  
  2375. the scanners (including the tables) are smaller.  Compared to LEX the  correct
  2376.  
  2377.  
  2378. scanner  specification  3 is processed nearly 20 times faster by Rex, the size
  2379.  
  2380.  
  2381. of the table is 10 times smaller, and the scanner is 4 times smaller.
  2382.  
  2383.  
  2384.  
  2385.      To compare the generated scanners (Table 2) we used a big  Modula-2  pro-
  2386.  
  2387.  
  2388. gram  as  input  whose characteristics are as follows: # of lines: 4,171, # of
  2389.  
  2390.  
  2391. characters: 100,268, # of tokens: 16,948.   The  timings  include  input  from
  2392.  
  2393.  
  2394. file,  scanning  and hashing of identifiers.  The Rex options -m and -c deter-
  2395.  
  2396.  
  2397. mine the target languages Modula-2 and C.   Compared  to  LEX  flex  yields  a
  2398.  
  2399.  
  2400. speed-up  of  1.8  with  options  -cem and a speed-up between 3.4 and 3.8 with
  2401.  
  2402.  
  2403. options -cf. The C version of Rex reaches a speed-up between  4  and  5.  This
  2404.  
  2405.  
  2406. speed  is  reached with analysers that are considerable smaller than flex gen-
  2407.  
  2408.  
  2409. erated ones.  The figures show that a  tunnel  automaton  can  be  implemented
  2410.  
  2411.  
  2412. efficiently:  Scanners  generated by Rex are 4 to 5 times faster than scanners
  2413.  
  2414.  
  2415. generated by LEX. More details can be found in reference[Gro87b].
  2416.  
  2417.  
  2418.  
  2419.  
  2420.  
  2421.  
  2422.  
  2423.  
  2424.  
  2425.  
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431.                                                                             30
  2432.  
  2433.  
  2434.  
  2435.                   Table 2: Comparison of Generated Scanners
  2436.  
  2437.  
  2438.  
  2439. _______________________________________________________________________________________
  2440.  
  2441.  
  2442.  generator            with hashing of identifiers and             without hashing and
  2443.  
  2444.  
  2445.                              number conversion                     number conversion
  2446.  
  2447. _______________________________________________________________________________________
  2448.  
  2449.  
  2450.              table size   scanner size     time          speed     time          speed
  2451.  
  2452.  
  2453.                 [bytes]        [bytes]   [sec.]   [lines/min.]   [sec.]   [lines/min.]
  2454.  
  2455. _______________________________________________________________________________________
  2456.  
  2457.  
  2458.  LEX             39,156         43,756     7.21         34,700     6.88         36,400
  2459.  
  2460.  
  2461.  flex -cem        2,868         18,140     3.99         62,700     3.69         67,800
  2462.  
  2463.  
  2464.  flex -cf        57,260         64,116     2.12        118,000     1.80        139,000
  2465.  
  2466.  
  2467.  Rex -m           4,306         13,672     3.00         83,400     2.22        112,700
  2468.  
  2469.  
  2470.  Rex -c           4,366         11,200     1.77        141,400     1.37        182,700
  2471.  
  2472. _______________________________________________________________________________________
  2473.  
  2474.  
  2475.  
  2476.  
  2477.  
  2478.  
  2479.  
  2480.  
  2481.  
  2482.  
  2483.  
  2484.  
  2485.  
  2486.  
  2487.  
  2488.  
  2489.  
  2490.  
  2491.  
  2492.  
  2493.  
  2494.  
  2495.  
  2496.  
  2497.  
  2498.  
  2499.  
  2500.  
  2501.  
  2502.  
  2503.  
  2504.  
  2505.  
  2506.           
  2507.  
  2508.  
  2509.  
  2510.  
  2511.  
  2512.  
  2513.  
  2514.  
  2515.  
  2516.  
  2517.  
  2518.  
  2519.  
  2520.  
  2521.  
  2522.  
  2523.  
  2524.  
  2525.  
  2526.  
  2527.  
  2528.  
  2529.  
  2530.  
  2531.  
  2532.  
  2533.  
  2534.  
  2535.  
  2536.  
  2537.  
  2538.                                                               
  2539.  
  2540.  
  2541.  
  2542.  
  2543.  
  2544.  
  2545.  
  2546.  
  2547.  
  2548.  
  2549.  
  2550.  
  2551.  
  2552.  
  2553.  
  2554.  
  2555.  
  2556.  
  2557.  
  2558.  
  2559.  
  2560.  
  2561.  
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.  
  2570.                                                                                       
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.  
  2582.  
  2583.  
  2584.  
  2585.  
  2586.  
  2587.  
  2588.  
  2589.  
  2590.  
  2591.  
  2592.  
  2593.  
  2594.  
  2595.  
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601.  
  2602.  
  2603.  
  2604.  
  2605.  
  2606.  
  2607.  
  2608.  
  2609.  
  2610.  
  2611.  
  2612.  
  2613.  
  2614.  
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.                                                                             31
  2627.  
  2628.  
  2629.                 Table 3: Comparison of Rex-Generated Scanners
  2630.  
  2631.  
  2632.  
  2633. __________________________________________________________________________________________
  2634.  
  2635.  
  2636.  language                    generator data                           scanner data
  2637.  
  2638. __________________________________________________________________________________________
  2639.  
  2640.  
  2641.             static size   dyn. memory   total memory     time   table size   scanner size
  2642.  
  2643.  
  2644.                 [bytes]       [bytes]        [bytes]   [sec.]      [bytes]        [bytes]
  2645.  
  2646. __________________________________________________________________________________________
  2647.  
  2648.  
  2649.  Pascal         102,970       238,464        341,434    87.40        4,426         13,128
  2650.  
  2651.  
  2652.  Modula         102,970       201,344        304,314     4.93        4,306         13,692
  2653.  
  2654.  
  2655.  Oberon         102,970       201,344        304,314     5.71        5,122         14,284
  2656.  
  2657.  
  2658.  C              102,970       201,344        304,314     7.24        5,702         13,296
  2659.  
  2660.  
  2661.  Ada            102,970       441,984        544,954   300.63        6,222         17,450
  2662.  
  2663. __________________________________________________________________________________________
  2664.  
  2665.  
  2666.  
  2667.  
  2668.  
  2669.  
  2670.  
  2671.  
  2672.  
  2673.  
  2674.  
  2675.  
  2676.  
  2677.  
  2678.  
  2679.  
  2680.  
  2681.  
  2682.  
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.          
  2695.  
  2696.  
  2697.  
  2698.  
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.                                                              
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.                                                                                          
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.  
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.  
  2780.  
  2781.  
  2782.  
  2783.  
  2784.  
  2785.  
  2786.      Table 3 compares scanners for different languages generated by Rex.   The
  2787.  
  2788.  
  2789. sizes  of the tables and the complete scanners all lie in the same range which
  2790.  
  2791.  
  2792. is relatively small. Only the generation times for Pascal and Ada  are  excep-
  2793.  
  2794.  
  2795. tionally long. The reason is that these languages allow keywords to be written
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.                                                                             32
  2810.  
  2811.  
  2812. with any letters no matter if upper or lower case. Therefore keywords  are  no
  2813.  
  2814.  
  2815. longer  constant  REs and can not be processed with the presented linear algo-
  2816.  
  2817.  
  2818. rithm.
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.                                   CONCLUSION
  2826.  
  2827.  
  2828.  
  2829.      The presented method allows the conversion of a NFA given by a set of REs
  2830.  
  2831.  
  2832. to a DFA in practically linear time. This holds under the assumption that only
  2833.  
  2834.  
  2835. a few non-constant but many constant REs have to be processed which is true in
  2836.  
  2837.  
  2838. many  practical cases. Compared to LEX we gained a speed-up of up to 20.  Com-
  2839.  
  2840.  
  2841. pared to flex which similarly improves  the  generation  times  the  generated
  2842.  
  2843.  
  2844. scanners  are  smaller  and  faster.   Not only is the generation time reduced
  2845.  
  2846.  
  2847. drastically but also the space requirement during generation of  the  scanner.
  2848.  
  2849.  
  2850. The  generator has to perform the subset construction, state minimization, and
  2851.  
  2852.  
  2853. table compression only for a few states. Therefore the space needed  by  those
  2854.  
  2855.  
  2856. algorithms  is  small.  The presented method directly constructs a space effi-
  2857.  
  2858.  
  2859. cient representation of the scanner control table which is used in combination
  2860.  
  2861.  
  2862.  
  2863.  
  2864.  
  2865.  
  2866.  
  2867.  
  2868.  
  2869.  
  2870.  
  2871.  
  2872.  
  2873.  
  2874.                                                                             33
  2875.  
  2876.  
  2877. with  the  comb-vector technique [ASU86].  The method allows the generation of
  2878.  
  2879.  
  2880. lexical analysers in a small amount  of  time.   The  generated  scanners  are
  2881.  
  2882.  
  2883. powerful  and  efficient  enough to be used in production compilers.  Finally,
  2884.  
  2885.  
  2886. scanner generators could be applied to a broader area than just compiler  con-
  2887.  
  2888.  
  2889. struction.
  2890.  
  2891.  
  2892.  
  2893.  
  2894.  
  2895.  
  2896.                                   REFERENCES
  2897.  
  2898.  
  2899.  
  2900. [AhC75]
  2901.  
  2902.  
  2903.      A. V. Aho and M. J.  Corasick,  Efficient  String  Matching:  An  Aid  to
  2904.  
  2905.  
  2906.      Bibliographic Search, Comm. ACM 18, 6 (June 1975), 333-340.
  2907.  
  2908.  
  2909.  
  2910. [ASU86]
  2911.  
  2912.  
  2913.      A. V. Aho, R. Sethi and J. D. Ullman, Compilers: Principles,  Techniques,
  2914.  
  2915.  
  2916.      and Tools, Addison Wesley, Reading, MA, 1986.
  2917.  
  2918.  
  2919.  
  2920. [Gro87a]
  2921.  
  2922.  
  2923.      J. Grosch, Rex - A Scanner Generator, Compiler Generation Report  No.  5,
  2924.  
  2925.  
  2926.      GMD Forschungsstelle an der Universitat Karlsruhe, Dec. 1987.
  2927.  
  2928.  
  2929.  
  2930.  
  2931.  
  2932.  
  2933.  
  2934.  
  2935.  
  2936.  
  2937.  
  2938.  
  2939.                                                                             34
  2940.  
  2941.  
  2942. [Gro87b]
  2943.  
  2944.  
  2945.      J. Grosch, An Efficient Table-Driven Scanner, Compiler Generation  Report
  2946.  
  2947.  
  2948.      No. 1, GMD Forschungsstelle an der Universitat Karlsruhe, May 1987.
  2949.  
  2950.  
  2951.  
  2952. [Gro88]
  2953.  
  2954.  
  2955.      J.  Grosch,  Selected  Examples  of  Scanner   Specifications,   Compiler
  2956.  
  2957.  
  2958.      Generation   Report  No.  7,  GMD  Forschungsstelle  an  der  Universitat
  2959.  
  2960.  
  2961.      Karlsruhe, Mar. 1988.
  2962.  
  2963.  
  2964.  
  2965. [Heu86]
  2966.  
  2967.  
  2968.      V. P. Heuring,  The  Automatic  Generation  of  Fast  Lexical  Analysers,
  2969.  
  2970.  
  2971.      Software-Practice & Experience 16, 9 (Sep. 1986), 801-808.
  2972.  
  2973.  
  2974.  
  2975. [HoL87]
  2976.  
  2977.  
  2978.      R. N. Horspool and M. R. Levy, Mkscan - An Interactive Scanner Generator,
  2979.  
  2980.  
  2981.      Software-Practice & Experience 17, 6 (June 1987), 369-378.
  2982.  
  2983.  
  2984.  
  2985. [Les75]
  2986.  
  2987.  
  2988.      M. E. Lesk,  LEX  -  A  Lexical  Analyzer  Generator,  Computing  Science
  2989.  
  2990.  
  2991.      Technical Report 39, Bell Telephone Laboratories, Murray Hill, NJ, 1975.
  2992.  
  2993.  
  2994.  
  2995.  
  2996.  
  2997.  
  2998.  
  2999.  
  3000.  
  3001.  
  3002.  
  3003.  
  3004.  
  3005.                                                                             35
  3006.  
  3007.  
  3008. [Moes86]
  3009.  
  3010.  
  3011.      H. Mossenbock, Alex - A Simple and Efficient Scanner  Generator,  SIGPLAN
  3012.  
  3013.  
  3014.      Notices 21, 12 (Dec. 1986), 139-148.
  3015.  
  3016.  
  3017.  
  3018. [Pax88]
  3019.  
  3020.  
  3021.      V. Paxson, Flex - Manual Pages, Public Domain Software, 1988.
  3022.  
  3023.  
  3024.  
  3025. [WaG84]
  3026.  
  3027.  
  3028.      W. M. Waite and G. Goos,  Compiler  Construction,  Springer  Verlag,  New
  3029.  
  3030.  
  3031.      York, NY, 1984.
  3032.  
  3033.  
  3034.  
  3035. [Wai86]
  3036.  
  3037.  
  3038.      W. M. Waite, The Cost of Lexical Analysis, Software-Practice & Experience
  3039.  
  3040.  
  3041.      16, 5 (May 1986), 473-488.
  3042.  
  3043.  
  3044.  
  3045. [Wir85]
  3046.  
  3047.  
  3048.      N. Wirth, Programming in Modula-2,  Springer  Verlag,  Heidelberg,  1985.
  3049.  
  3050.  
  3051.      Third Edition.
  3052.  
  3053.  
  3054.  
  3055.  
  3056.  
  3057.  
  3058.  
  3059.  
  3060.  
  3061.  
  3062.  
  3063.  
  3064.  
  3065.  
  3066.  
  3067.  
  3068.  
  3069.  
  3070.                                                                             36
  3071.  
  3072.  
  3073.                                     APPENDIX 1
  3074.  
  3075.  
  3076.  
  3077.  
  3078.      Algorithm 4: ambiguous states of a tunnel automaton (with one start state)
  3079.  
  3080.  
  3081.  
  3082.      BEGIN
  3083.  
  3084.  
  3085.  
  3086.         /* transition function using the tunnel function */
  3087.  
  3088.  
  3089.  
  3090.         PROCEDURE NextState (State, Symbol)
  3091.  
  3092.  
  3093.            BEGIN
  3094.  
  3095.  
  3096.               LOOP
  3097.  
  3098.  
  3099.                  IF Control (State, Symbol) / NoState THEN
  3100.  
  3101.  
  3102.                     RETURN Control (State, Symbol)
  3103.  
  3104.  
  3105.                  ELSE
  3106.  
  3107.  
  3108.                     State := Tunnel (State)
  3109.  
  3110.  
  3111.                     IF State = NoState THEN RETURN NoState END
  3112.  
  3113.  
  3114.                  END
  3115.  
  3116.  
  3117.               END
  3118.  
  3119.  
  3120.            END
  3121.  
  3122.  
  3123.  
  3124.  
  3125.  
  3126.  
  3127.  
  3128.  
  3129.  
  3130.  
  3131.  
  3132.  
  3133.  
  3134.                                                                             37
  3135.  
  3136.  
  3137.         /* compute the number of predecessors */
  3138.  
  3139.  
  3140.  
  3141.         FORALL State  StateSet DO
  3142.  
  3143.  
  3144.            PredCount (State) := 0
  3145.  
  3146.  
  3147.         END
  3148.  
  3149.  
  3150.  
  3151.         FORALL State  StateSet DO
  3152.  
  3153.  
  3154.            FORALL Symbol  Vocabulary DO
  3155.  
  3156.  
  3157.               PredCount (NextState (State, Symbol)) +:= 1
  3158.  
  3159.  
  3160.            END
  3161.  
  3162.  
  3163.         END
  3164.  
  3165.  
  3166.  
  3167.         /* iteratively remove states with 1 predecessor */
  3168.  
  3169.  
  3170.  
  3171.         AmbiguousStates   := StateSet - { NoState }
  3172.  
  3173.  
  3174.         UnambiguousStates := { StartState }
  3175.  
  3176.  
  3177.  
  3178.         WHILE UnambiguousStates /  DO
  3179.  
  3180.  
  3181.            State := SELECT UnambiguousStates
  3182.  
  3183.  
  3184.            UnambiguousStates -:= { State }
  3185.  
  3186.  
  3187.  
  3188.  
  3189.  
  3190.  
  3191.  
  3192.  
  3193.  
  3194.  
  3195.  
  3196.  
  3197.                                                                             38
  3198.  
  3199.  
  3200.            AmbiguousStates   -:= { State }
  3201.  
  3202.  
  3203.            FORALL Symbol  Vocabulary DO
  3204.  
  3205.  
  3206.               Successor := NextState (State, Symbol)
  3207.  
  3208.  
  3209.               IF PredCount (Successor) = 1 THEN
  3210.  
  3211.  
  3212.                  UnambiguousStates U:= { Successor }
  3213.  
  3214.  
  3215.               END
  3216.  
  3217.  
  3218.            END
  3219.  
  3220.  
  3221.         END
  3222.  
  3223.  
  3224.      END
  3225.  
  3226.  
  3227.  
  3228.  
  3229.  
  3230.  
  3231.  
  3232.  
  3233.  
  3234.  
  3235.  
  3236.  
  3237.  
  3238.  
  3239.  
  3240.  
  3241.  
  3242.  
  3243.  
  3244.  
  3245.  
  3246.  
  3247.  
  3248.  
  3249.  
  3250.  
  3251.  
  3252.  
  3253.  
  3254.  
  3255.  
  3256.  
  3257.  
  3258.  
  3259.  
  3260.  
  3261.  
  3262.                                                                             39
  3263.  
  3264.  
  3265.                                     APPENDIX 2
  3266.  
  3267.  
  3268.  
  3269. An example of a scanner specification for Modula-2 in Rex syntax:
  3270.  
  3271.  
  3272.  
  3273.  
  3274.  
  3275.  
  3276. GLOBAL  { VAR NestingLevel: CARDINAL; }
  3277.  
  3278.  
  3279.  
  3280. BEGIN   { NestingLevel := 0; }
  3281.  
  3282.  
  3283.  
  3284. DEFAULT { Error ("illegal character:"); yyEcho; }
  3285.  
  3286.  
  3287.  
  3288. EOF     { IF yyStartState = comment THEN Error ("unclosed comment"); END; }
  3289.  
  3290.  
  3291.  
  3292. DEFINE
  3293.  
  3294.  
  3295.  
  3296.    digit        = {0-9}         .
  3297.  
  3298.  
  3299.    letter       = {a-z A-Z}     .
  3300.  
  3301.  
  3302.    cmt          = - {*(\t\n}    .
  3303.  
  3304.  
  3305.  
  3306. START   comment
  3307.  
  3308.  
  3309.  
  3310. RULES
  3311.  
  3312.  
  3313.  
  3314.  
  3315.  
  3316.  
  3317.  
  3318.  
  3319.  
  3320.  
  3321.  
  3322.  
  3323.  
  3324.                                                                             40
  3325.  
  3326.  
  3327.            "(*"         : {INC (NestingLevel); yyStart (comment);}
  3328.  
  3329.  
  3330. #comment#  "*)"         : {DEC (NestingLevel); IF NestingLevel = 0 THEN yyStart (STD); END;}
  3331.  
  3332.  
  3333. #comment#  "(" | "*" | cmt + : {}
  3334.  
  3335.  
  3336.  
  3337. #STD# digit +           ,
  3338.  
  3339.  
  3340. #STD# digit + / ".."    : {RETURN 1;}
  3341.  
  3342.  
  3343. #STD# {0-7} + B         : {RETURN 2;}
  3344.  
  3345.  
  3346. #STD# {0-7} + C         : {RETURN 3;}
  3347.  
  3348.  
  3349. #STD# digit {0-9 A-F} * H : {RETURN 4;}
  3350.  
  3351.  
  3352. #STD# digit + "." digit * (E {+\-} ? digit +) ? : {RETURN 5;}
  3353.  
  3354.  
  3355.  
  3356. #STD# ' - {\n'} * '     |
  3357.  
  3358.  
  3359.       \" - {\n"} * \"   : {RETURN 6;}
  3360.  
  3361.  
  3362.  
  3363. #STD# ":"               : {RETURN 7;}
  3364.  
  3365.  
  3366. #STD# "="               : {RETURN 8;}
  3367.  
  3368.  
  3369. #STD# ":="              : {RETURN 9;}
  3370.  
  3371.  
  3372. ...
  3373.  
  3374.  
  3375.  
  3376.  
  3377.  
  3378.  
  3379.  
  3380.  
  3381.  
  3382.  
  3383.  
  3384.  
  3385.  
  3386.  
  3387.  
  3388.                                                                             41
  3389.  
  3390.  
  3391. #STD# AND               : {RETURN 34;}
  3392.  
  3393.  
  3394. #STD# ARRAY             : {RETURN 35;}
  3395.  
  3396.  
  3397. #STD# BEGIN             : {RETURN 36;}
  3398.  
  3399.  
  3400. ...
  3401.  
  3402.  
  3403.  
  3404. #STD# letter (letter | digit) * : {RETURN 74;}
  3405.  
  3406.  
  3407.  
  3408.  
  3409.  
  3410.  
  3411.  
  3412.  
  3413.  
  3414.  
  3415.  
  3416.  
  3417.  
  3418.  
  3419.  
  3420.  
  3421.  
  3422.  
  3423.  
  3424.  
  3425.  
  3426.  
  3427.  
  3428.  
  3429.  
  3430.  
  3431.  
  3432.  
  3433.  
  3434.  
  3435.  
  3436.  
  3437.  
  3438.  
  3439.  
  3440.  
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446.  
  3447.  
  3448.  
  3449.  
  3450.  
  3451.  
  3452.  
  3453.                                                                              1
  3454.  
  3455.  
  3456. Contents
  3457.  
  3458.  
  3459.  
  3460.  
  3461.  
  3462. 1.      Introduction ....................................................    2
  3463.  
  3464.  
  3465. 2.      The Method ......................................................    6
  3466.  
  3467.  
  3468. 3.      Example .........................................................   20
  3469.  
  3470.  
  3471. 4.      Several Start States ............................................   23
  3472.  
  3473.  
  3474. 5.      Experimental Results ............................................   25
  3475.  
  3476.  
  3477. 6.      Conclusion ......................................................   32
  3478.  
  3479.  
  3480.         References ......................................................   33
  3481.  
  3482.  
  3483.         Appendix 1 ......................................................   36
  3484.  
  3485.  
  3486.         Appendix 2 ......................................................   39
  3487.  
  3488.  
  3489.  
  3490.  
  3491.  
  3492.  
  3493.  
  3494.  
  3495.  
  3496.  
  3497.  
  3498.  
  3499.  
  3500.  
  3501.  
  3502.  
  3503.  
  3504.  
  3505.  
  3506.  
  3507.  
  3508.  
  3509.  
  3510.  
  3511.  
  3512.